package net.xumf.support.handle;

import lombok.extern.slf4j.Slf4j;
import net.xumf.support.enums.CodeEnum;
import net.xumf.support.exception.*;
import net.xumf.support.model.ResponseResult;
import org.hibernate.HibernateException;
import org.quartz.ObjectAlreadyExistsException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.mail.MailAuthenticationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@Slf4j
@ControllerAdvice
@ResponseBody
public class ExceptionHandle {

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public ResponseResult action(Exception e) {
        log.error("exception错误", e);
        return generateResponseResultByEnum(CodeEnum.FAILURE);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(NullPointerException.class)
    public ResponseResult action(NullPointerException e) {
        log.error("NullPointerException错误", e);
        return generateResponseResultByEnum(CodeEnum.FAILURE);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(ClassNotFoundException.class)
    public ResponseResult action(ClassNotFoundException e) {
        log.error("ClassNotFoundException错误", e);
        return generateResponseResultByEnum(CodeEnum.FAILURE);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(HibernateException.class)
    public ResponseResult action(HibernateException e) {
        log.error("HibernateException错误", e);
        return generateResponseResultByEnum(CodeEnum.SQL_ACTION_ERROR);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseResult action(IllegalArgumentException e) {
        log.error("IllegalArgumentException错误", e);
        return generateResponseResultByEnum(CodeEnum.REQUEST_PARAM_ERROR);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(SystemLogException.class)
    public ResponseResult action(SystemLogException e) {
        log.error("SystemLogException错误", e);
        return generateResponseResult(e);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(ObjectAlreadyExistsException.class)
    public ResponseResult action(ObjectAlreadyExistsException e) {
        log.error("ObjectAlreadyExistsException错误", e);
        return generateResponseResultByEnum(CodeEnum.QUARTZ_ALREADY_EXISTS);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({SystemException.class})
    public ResponseResult action(SystemException e) {
        log.error("SystemException错误", e);
        return generateResponseResult(e);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(MailAuthenticationException.class)
    public ResponseResult action(MailAuthenticationException e) {
        log.error("MailAuthenticationException错误", e);
        return generateResponseResultByEnum(CodeEnum.MAIL_AUTHENTICATION_FAIL);
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResponseResult action(DataIntegrityViolationException e) {
        log.error("DataIntegrityViolationException错误", e);
        return generateResponseResultByEnum(CodeEnum.SQL_ACTION_ERROR);
    }


    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({
            NotFoundDataRowInfoException.class, EmptyResultDataAccessException.class, UserLoginException.class,
            NotFoundEnumInfoException.class
    })
    public ResponseResult action(AbstractCommonException e) {
        log.error("AbstractCommonException错误", e);
        return generateResponseResult(e);
    }

    /**
     * 构造 {@link ResponseResult}
     *
     * @param e   {@link CodeEnum} 子类与自己
     * @param <T> {@link CodeEnum} 子类与自己
     * @return {@link ResponseResult}
     */
    private <T extends CodeEnum> ResponseResult generateResponseResultByEnum(T e) {
        return ResponseResult.failure(e, generateErrorMessageByEnum(e));
    }

    /**
     * 构造 {@link ResponseResult}
     *
     * @param e   {@link AbstractCommonException} 子类与自己
     * @param <T> {@link AbstractCommonException} 子类与自己
     * @return {@link ResponseResult}
     */
    private <T extends AbstractCommonException> ResponseResult generateResponseResult(T e) {
        return ResponseResult.failure(e.getCode(), generateErrorMessage(e));
    }

    /**
     * 构造错误信息
     *
     * @param e   {@link AbstractCommonException} 子类与自己
     * @param <T> {@link AbstractCommonException} 子类与自己
     * @return 错误信息
     */
    private <T extends AbstractCommonException> String generateErrorMessage(T e) {
        return e.getMessage().concat("[").concat(e.getCode().toString()).concat("]");
    }

    /**
     * 构造错误信息
     *
     * @param e   {@link CodeEnum} 子类与自己
     * @param <T> {@link CodeEnum} 子类与自己
     * @return 错误信息
     */
    private <T extends CodeEnum> String generateErrorMessageByEnum(T e) {
        return e.getMsg().concat("[").concat(e.getCode() + "").concat("]");
    }

}
